<template>
    <div class="preview-image-container">
        <div class="image-wrapper" :class="{ 'zoom-in': zoomed }" @click="$emit('zoom')">
            <img :src="url" :alt="file.name" @load="onLoad" @error="onError" ref="imageRef"
                :class="{ loaded: imageLoaded }" />
            <div v-if="!imageLoaded && !imageError" class="loading-overlay">
                <div class="loading-spinner"></div>
                <span>加载中...</span>
            </div>
            <div v-if="imageError" class="error-overlay">
                <div class="error-icon">❌</div>
                <p>图片加载失败</p>
                <el-button type="primary" @click.stop="retryLoad" size="small">重试</el-button>
            </div>
        </div>
        <div class="image-info" v-if="imageInfo && imageLoaded">
            {{ imageInfo.width }} × {{ imageInfo.height }} ({{ formatFileSize(file.size) }})
            <span v-if="zoomed" class="zoom-tip">(点击图片退出缩放模式)</span>
        </div>
    </div>
</template>

<script setup>
import { ref } from 'vue'

const props = defineProps({
    file: {
        type: Object,
        required: true
    },
    url: {
        type: String,
        required: true
    },
    zoomed: {
        type: Boolean,
        default: false
    }
})

const emit = defineEmits(['loaded', 'error', 'zoom'])

const imageRef = ref(null)
const imageInfo = ref(null)
const imageLoaded = ref(false)
const imageError = ref(false)

const formatFileSize = (size) => {
    if (size === undefined || size === null || size === 0) return '0 Bytes'
    if (isNaN(size)) return '未知大小'
    const k = 1024
    const sizes = ['Bytes', 'KB', 'MB', 'GB']
    const i = Math.floor(Math.log(size) / Math.log(k))
    return parseFloat((size / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

const onLoad = () => {
    if (imageRef.value) {
        imageInfo.value = {
            width: imageRef.value.naturalWidth,
            height: imageRef.value.naturalHeight,
        }
        imageLoaded.value = true
        imageError.value = false
        emit('loaded', imageInfo.value)
    }
}

const onError = (e) => {
    imageLoaded.value = false
    imageError.value = true
    emit('error', e)
}

const retryLoad = () => {
    imageError.value = false
    imageLoaded.value = false
    // 重新触发图片加载
    if (imageRef.value) {
        imageRef.value.src = props.url
    }
}
</script>

<style scoped>
.preview-image-container {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    overflow: hidden;
    background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
    border-radius: 10px;
    position: relative;
}

.image-wrapper {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 100%;
    cursor: zoom-in;
    transition: transform 0.3s ease;
    position: relative;
}

.image-wrapper.zoom-in {
    cursor: zoom-out;
    position: relative;
}

.image-wrapper.zoom-in img {
    max-width: none;
    max-height: none;
    width: auto;
    height: auto;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
    border-radius: 4px;
}

.preview-image-container img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: 8px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
    opacity: 0;
    transition: opacity 0.3s ease;
}

.preview-image-container img.loaded {
    opacity: 1;
}

.loading-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    background-color: rgba(255, 255, 255, 0.8);
    z-index: 10;
    border-radius: 8px;
}

.loading-spinner {
    width: 32px;
    height: 32px;
    border: 3px solid #e2e8f0;
    border-top: 3px solid #4299e1;
    border-radius: 50%;
    animation: spin 1s linear infinite;
    margin-bottom: 12px;
}

@keyframes spin {
    0% {
        transform: rotate(0deg);
    }

    100% {
        transform: rotate(360deg);
    }
}

.error-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    background-color: rgba(255, 255, 255, 0.9);
    z-index: 10;
    border-radius: 8px;
    color: #e53e3e;
    text-align: center;
}

.error-icon {
    font-size: 40px;
    margin-bottom: 12px;
}

.image-info {
    margin-top: 15px;
    font-size: 14px;
    color: #4a5568;
    background-color: rgba(255, 255, 255, 0.8);
    padding: 8px 16px;
    border-radius: 20px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.image-info .zoom-tip {
    font-style: italic;
    color: #718096;
    margin-left: 10px;
    font-size: 12px;
}

@media (max-width: 768px) {
    .image-info {
        font-size: 13px;
        padding: 6px 12px;
    }

    .error-icon {
        font-size: 32px;
    }

    .loading-spinner {
        width: 28px;
        height: 28px;
    }
}
</style>
